﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lizk.SimpleHUD;

namespace SharpMedia.Controls
{
    /// <summary>
    /// A scrollbar for movelists
    /// </summary>
    public class HUDListScroller : HUDContainerSimple
    {
        /// <summary>
        /// The list this scrollbar representts
        /// </summary>
        public HUDMoveList List { get; set; }
        
        /// <summary>
        /// The scrollbar track
        /// </summary>
        HUDImage track;

        /// <summary>
        /// The indicator
        /// </summary>
        HUDImage indicator;

        /// <summary>
        /// The button that decreases startindex
        /// </summary>
        HUDImage minusImage;
        
        /// <summary>
        /// The button that increases startindex
        /// </summary>
        HUDImage plusImage;

        public HUDListScroller(HUDMoveList list)
        {
            this.List = list;

            // add the images to this container
            track = new HUDImage("white.png")
            {
                Anchor = Anchor.All,
                ConstrainProportions = false,
                Color = ColorS.White,
                Alpha = 50,
                Size = this.Size
            };
            Add(track);

            indicator = new HUDImage(list.IsHorizontal ? "scroll_horizontal.png" : "scroll_vertical.png")
            {
                Anchor = Anchor.All,
                ConstrainProportions = false,
                Size = this.Size,
                Alpha = 200
            };
            Add(indicator);
            indicator.OnMouseEnter += new EventHandler<MouseEventArgs>(indicator_OnMouseEnter);
            indicator.OnMouseExit += new EventHandler<MouseEventArgs>(indicator_OnMouseExit);
            indicator.OnMouseDown += new EventHandler<MouseEventArgs>(indicator_OnMouseDown);

            minusImage = new HUDImage(list.IsHorizontal ? "scroll_left.png" : "scroll_up.png")
            {
                Alpha = 200
            };
            Add(minusImage);
            minusImage.OnMouseEnter += new EventHandler<MouseEventArgs>(indicator_OnMouseEnter);
            minusImage.OnMouseExit += new EventHandler<MouseEventArgs>(indicator_OnMouseExit);
            minusImage.OnMouseDown += new EventHandler<MouseEventArgs>(minusImage_OnMouseDown);

            plusImage = new HUDImage(list.IsHorizontal ?"scroll_right.png" : "scroll_down.png")
            {
                Alpha = 200
            };
            Add(plusImage);
            plusImage.OnMouseEnter += new EventHandler<MouseEventArgs>(indicator_OnMouseEnter);
            plusImage.OnMouseExit += new EventHandler<MouseEventArgs>(indicator_OnMouseExit);
            plusImage.OnMouseDown += new EventHandler<MouseEventArgs>(plusImage_OnMouseDown);
        }

        void indicator_OnMouseDown(object sender, HUDControl.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                dragging = true;
                dragStart = e.Point;
                oldPosition = indicator.Location;
            }
        }

        void plusImage_OnMouseDown(object sender, HUDControl.MouseEventArgs e)
        {
            if (List.StartIndex + List.VisibleItems + 1  < List.Count)
            {
                List.SetIndices(List.StartIndex + 1, List.StartIndex + 1 + List.VisibleItems, true);
                
            }
        }

        void minusImage_OnMouseDown(object sender, HUDControl.MouseEventArgs e)
        {
            

            if (List.StartIndex > 0)
            {
                List.SetIndices(List.StartIndex - 1, List.StartIndex - 1, true);
            }
        }

        void indicator_OnMouseExit(object sender, HUDControl.MouseEventArgs e)
        {
            HUDControl c = (HUDControl)sender;
            c.Fade(200, 6f);
        }

        void indicator_OnMouseEnter(object sender, HUDControl.MouseEventArgs e)
        {
            HUDControl c = (HUDControl)sender;
            c.Fade(255, 6f);
            
        }

        public bool IsDragging { get { return dragging; } }

        private bool dragging = false;
        private PointS dragStart = PointS.Empty;
        private PointS oldPosition = PointS.Empty;
        private PointS mousePos = PointS.Empty;

        public override void UpdateMousePosition(PointS position)
        {
            base.UpdateMousePosition(position);
            mousePos = position; ;
        }


        public override void Update(TimeSpan ts)
        {
            base.Update(ts);
            if (List == null || List.Count <= 1 || SharpMedia.Engine.IsCursorHidden)
            {
                dragging = false;
                Fade(0,6f);
            }
            else
            {
                Fade(255, 6f);
            }
            if (dragging && !((SharpMedia.PressedMouseButtons & MouseButtons.Left) == MouseButtons.Left))
            {
                dragging = false;
                //indicator.Location = new PointS(oldPosition.X + (position.X - dragStart.X), 0);
            }

            if (dragging)
            {
                // for horizontal
                if (List.IsHorizontal)
                {
                    // find the index represented by the indicators new position
                    float location = oldPosition.X + (mousePos.X - AbsoluteBounds.X - dragStart.X) - Size.Height;
                    int index = (int)(location / (Size.Width - Size.Height * 2f) * (float)List.Count);

                    int max = List.Count - List.VisibleItems - 1;
                    index = Math.Min(Math.Max(index, 0), max);

                    

                    int selectedIndex = Math.Min(Math.Max(index, List.SelectedIndex), index + List.VisibleItems );
                    List.SetIndices(index, selectedIndex, true);
                }
                else
                {
                    // find the index represented by the indicators new position
                    float location = oldPosition.Y + (mousePos.Y - AbsoluteBounds.Y - dragStart.Y) - Size.Width;
                    float index = (location / (Size.Height - Size.Width * 2f) * (float)List.Count);

                    int max = List.Count - List.VisibleItems - 1;
                    index = Math.Min(Math.Max(index, 0), max);
                    int selectedIndex = Math.Min(Math.Max((int)index, List.SelectedIndex), (int)index + List.VisibleItems);
                    List.SetIndices((int)index, selectedIndex, true);
                }
            }

            // in every update we set the size of the indicator to match the selection of the list.

            // if there are no items, just set marker size to max

            {
                // If the list is horizontal, we work on the width, else we work on the height
                if (List.IsHorizontal)
                {
                    // Set position of buttons
                    minusImage.Location = PointS.Empty;
                    minusImage.Size = new SizeS(Size.Height, Size.Height);
                    plusImage.Location = new PointS(Size.Width - Size.Height, 0);
                    plusImage.Size = new SizeS(Size.Height, Size.Height);


                    // first calculate the width of the marker
                    float markerWidth = (float)(List.VisibleItems + 1) / (float)List.Count * (Size.Width - Size.Height * 2);

                    // then the position
                    float markerPosition = (float)List.StartIndex / (float)List.Count * (Size.Width - Size.Height * 2);

                    indicator.Destination = new PointS(markerPosition + minusImage.Size.Width, 0);
                    indicator.DestinationSize = new PointS(markerWidth, Size.Height);
                }
                else
                {
                    // Set position of buttons
                    minusImage.Location = PointS.Empty;
                    minusImage.Size = new SizeS(Size.Width, Size.Width);
                    plusImage.Location = new PointS(0, Size.Height - Size.Width);
                    plusImage.Size = new SizeS(Size.Width, Size.Width);


                    // first calculate the width of the marker
                    float markerHeight = (float)(List.VisibleItems + 1) / (float)List.Count * (Size.Height - Size.Width * 2);

                    // then the position
                    float markerPosition = (float)List.StartIndex / (float)List.Count * (Size.Height - Size.Width * 2);

                    indicator.Destination = new PointS(0, markerPosition + minusImage.Size.Height);
                    indicator.DestinationSize = new PointS(Size.Width, markerHeight);

                }
            }
        }
        

    }
}
